package com.mcxx.modules.minimumliving.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.mcxx.common.exception.BizException;
import com.mcxx.constant.MQConstant;
import com.mcxx.convert.ApplyConvert;
import com.mcxx.modules.common.service.impl.IntegrateCheckServiceImpl;
import com.mcxx.modules.minimumliving.service.BacklogService;
import com.mcxx.modules.minimumliving.service.RecheckService;
import com.mcxx.modules.minimumliving.service.ScheduleCheckService;
import com.mcxx.modules.minimumliving.service.SuspendManagementService;
import com.mcxx.modules.base.service.read.RuleEngineReadService;
import com.mcxx.modules.base.utils.QueryParamUtil;
import com.mcxx.modules.filemanage.easypoi.util.ExportExcelService;
import com.mcxx.modules.filemanage.file.service.FileService;
import com.mcxx.modules.miniSalvation.check.entity.CheckEntity;
import com.mcxx.modules.miniSalvation.check.service.read.CheckReadService;
import com.mcxx.modules.miniSalvation.check.service.write.CheckWriteService;
import com.mcxx.modules.miniSalvation.check.service.write.RecheckWriteService;
import com.mcxx.modules.miniSalvation.family.dto.ApplyRtnDTO;
import com.mcxx.modules.miniSalvation.family.dto.MininumLivingApplyDTO;
import com.mcxx.modules.miniSalvation.family.entity.*;
import com.mcxx.modules.miniSalvation.family.service.read.*;
import com.mcxx.modules.miniSalvation.family.service.write.*;
import com.mcxx.modules.miniSalvation.fundpay.service.read.FundPayReadService;
import com.mcxx.modules.miniSalvation.order.dto.*;
import com.mcxx.modules.miniSalvation.order.entity.OrderCertEntity;
import com.mcxx.modules.miniSalvation.order.entity.OrderDetailEntity;
import com.mcxx.modules.miniSalvation.order.entity.OrderEntity;
import com.mcxx.modules.miniSalvation.order.param.CheckParam;
import com.mcxx.modules.miniSalvation.order.param.RecheckOrderQueryParam;
import com.mcxx.modules.miniSalvation.order.param.RecheckParam;
import com.mcxx.modules.miniSalvation.order.service.read.IncomeCalculateReadService;
import com.mcxx.modules.miniSalvation.order.service.read.OrderCertReadService;
import com.mcxx.modules.miniSalvation.order.service.read.OrderReadService;
import com.mcxx.modules.miniSalvation.order.service.write.*;
import com.mcxx.modules.miniSalvation.salary.service.read.FamilyMemberSalaryReadService;
import com.mcxx.modules.miniSalvation.salary.service.read.FamilySalaryReadService;
import com.mcxx.modules.miniSalvation.salary.service.write.FamilySalaryWriteService;
import com.mcxx.modules.miniSalvation.salary.service.write.SalaryChangeWriteService;
import com.mcxx.modules.system.dto.MQMessageDTO;
import com.mcxx.modules.system.service.write.TaskExportWriteService;
import com.mcxx.result.BaseResult;
import com.mcxx.util.CommonUtil;
import com.mcxx.util.Constant;
import com.mcxx.util.FailureCode;
import com.yinhai.ta404.component.audit.vo.ExcelInfo;
import com.yinhai.ta404.core.security.vo.UserAccountVo;
import com.yinhai.ta404.core.transaction.annotation.TaTransactional;
import com.yinhai.ta404.core.utils.StringUtils;
import com.yinhai.ta404.core.validate.annotation.V;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;


@Service("recheckService")
@TaTransactional
public class RecheckServiceImpl implements RecheckService {

    @Autowired
    private OrderReadService orderReadService;
    @Autowired
    private OrderWriteService orderWriteService;
    @Autowired
    private OrderCertWriteService orderCertWriteService;
    @Autowired
    private FamilySalaryReadService familySalaryReadService;
    @Autowired
    private FamilySalaryWriteService familySalaryWriteService;
    @Autowired
    private FamilyMainReadService familyMainReadService;
    @Autowired
    private FamilyMemberReadService familyMemberReadService;
    @Autowired
    private CheckWriteService checkWriteService;
    @Autowired
    private RecheckWriteService recheckWriteService;
    @Autowired
    private CheckReadService checkReadService;
    @Autowired
    private MemberAssetsReadService memberAssetsReadService;
    @Autowired
    private FamilyMainTempWriteService familyMainTempWriteService;
    @Autowired
    private FamilyMemberTempWriteService familyMemberTempWriteService;
    @Autowired
    private FamilyMainHistoryWriteService familyMainHistoryWriteService;
    @Autowired
    private FamilyMemberHistoryWriteService familyMemberHistoryWriteService;
    @Autowired
    private FamilyMainTempReadService familyMainTempReadService;
    @Autowired
    private FamilyMemberTempReadService familyMemberTempReadService;
    @Autowired
    private BacklogService backlogService;
    @Autowired
    private FamilyMainWriteService familyMainWriteService;
    @Autowired
    private FamilyMemberWriteService familyMemberWriteService;
    @Autowired
    private RuleEngineReadService ruleEngineReadService;
    @Autowired
    private MemberAssetsWriteService memberAssetsWriteService;
    @Autowired
    private OrderCertReadService orderCertReadService;
    @Autowired
    private FamilyMemberSalaryReadService memberSalaryReadService;
    @Autowired
    private InHouseWriteService inHouseWriteService;
    @Autowired
    private ScheduleCheckService scheduleCheckService;
    @Autowired
    private IncomeCalculateReadService incomeCalculateReadService;
    @Autowired
    private IncomeCalculateWriteService incomeCalculateWriteService;
    @Autowired
    private ExportExcelService exportExcelService;
    @Autowired
    private FileService fileService;
    @Autowired
    private TaskExportWriteService taskExportWriteService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private BankWriteService bankWriteService;
    @Autowired
    private IntegrateCheckServiceImpl integrateCheckService;
    @Autowired
    private OrderDetailWriteService orderDetailWriteService;
    @Autowired
    private SuspendManagementService suspendManagementService;
    @Autowired
    private NoticeBoardDetailWriteService noticeBoardDetailWriteService;
    @Autowired
    private FundPayReadService fundPayReadService;
    @Autowired
    private SalaryChangeWriteService salaryChangeWriteService;
    private final static Logger log = LoggerFactory.getLogger(RecheckServiceImpl.class);

    @Override
    public String addRecheckOrder(String orderId, UserAccountVo accountVo) {
        OrderEntity order = orderReadService.getOrderById(orderId);


        String recheckOrderId = checkIfMeetConditionsOfRecheck(order);
        if (!CommonUtil.invalidArgs(recheckOrderId)) {

            return recheckOrderId;
        }

        String newOrderId = IdUtil.simpleUUID();


        DateTime now = DateUtil.date();
        double totalFee = familySalaryReadService.getTotalFeeByOrderId(orderId, now.toString("yyyyMM"));
        order.setOrderId(newOrderId);
        order.setType(Constant.OrderType.RECHECK);

        order.setState(Constant.BizState.SALVATION);
        order.setBizState(Constant.BizState.SALVATION);
        order.setSourOrderId(orderId);
        order.setBeforeChkMoney(totalFee);
        order.setRemark(null);
        order.setCheckDate(null);
        order.setAcceptDate(null);
        order.setStartMonth(null);
        order.setReason(null);
        order.setCreateTime(now);
        order.setUpdateTime(now);
        order.setCommitDate(now);
        order.setCreateBy(accountVo.getUserId());
        order.setOrgId(accountVo.getOrgId());

        order.setSaveMemberNumber(0);
        order.setCountType(null);
        order.setSalvMoney(null);
        order.setBaseSalary(null);

        if(CommonUtil.invalidArgs(order.getApplyName())){
            order.setApplyName(order.getName());
            order.setApplyIdcard(order.getIdcard());
        }
        orderWriteService.insertIgnoreNull(order);


        backupFamilyAndFamilyMember(order.getFamilyId(),newOrderId);


        backupMemberAssets(order.getFamilyId(),newOrderId,orderId);


        orderWriteService.updateOrderRecheckFlag(orderId,Constant.RECHECK_FLAG.YES, order.getVersion());

        FamilyMainEntity familyMainEntitys = familyMainReadService.getById(order.getFamilyId());


        FamilyMainEntity familyMainEntity = new FamilyMainEntity();
        if(Constant.MinimumLivingType.OTHER.equals(familyMainEntitys.getFamilyObjectType())){
            familyMainEntity.setFamilyObjectType(Constant.MinimumLivingType.HOUSEHOLD);
        }
        familyMainEntity.setId(order.getFamilyId());
        familyMainEntity.setSaveMemberNumber(0);
        familyMainWriteService.updateFamily(familyMainEntity);

        familyMemberWriteService.updateNoSave(order.getFamilyId());

        OrderCertEntity orderCert = new OrderCertEntity();
        orderCert.setOrderId(orderId);
        orderCert.setAssociationTable("'1','2','6','7'");
        orderCert.setAssociationTableId(newOrderId);
        orderCertWriteService.insertCopy(orderCert);

        incomeCalculateWriteService.backupCalculate(orderId,newOrderId);
        return newOrderId;
    }


    public void addRecheckOrder(OrderEntity orderEntity, UserAccountVo accountVo) {

        OrderEntity order = new OrderEntity();
        BeanUtils.copyProperties(orderEntity,order);


        String recheckOrderId = checkIfMeetConditionsOfRecheck(order);
        if (!CommonUtil.invalidArgs(recheckOrderId)) {
            throw new BizException("-1","该业务正在复查中，不能操作停保");
        }
        String orderId = order.getOrderId();
        String newOrderId = IdUtil.simpleUUID();


        DateTime now = DateUtil.date();
        double totalFee = familySalaryReadService.getTotalFeeByOrderId(order.getOrderId(), now.toString("yyyyMM"));
        order.setOrderId(newOrderId);
        order.setType(Constant.OrderType.EXPIRE);
        order.setState(Constant.BizState.APPROVE_YES);
        order.setBizState(Constant.BizState.APPROVE_YES);
        order.setSourOrderId(orderId);
        order.setBeforeChkMoney(totalFee);
        order.setReason("批量停保");
        order.setRemark("批量停保");
        order.setCheckDate(now);
        order.setAcceptDate(now);
        order.setCreateTime(now);
        order.setUpdateTime(now);
        order.setCreateBy(accountVo.getUserId());
        order.setOrgId(accountVo.getOrgId());
        orderWriteService.insertIgnoreNull(order);


        familyMainHistoryWriteService.copyHistoryRecordByOrderId(orderId,newOrderId);
        familyMemberHistoryWriteService.copyHistoryRecordByOrderId(orderId,newOrderId);

        orderWriteService.updateOrderRecheckFlag(orderId,Constant.RECHECK_FLAG.YES, order.getVersion());
    }


    @Override
    public void approveRecheckOrder(OrderApproveDTO orderApproveDTO, UserAccountVo accountVo) {

        backlogService.approveSalvationRequest(orderApproveDTO, accountVo);

        OrderEntity order = orderReadService.getOrderById(orderApproveDTO.getOrderId());
        if("1".equals(orderApproveDTO.getApprovalResult())) {

            String lastMonth = DateUtil.parse(orderApproveDTO.getRescueYears(), "yyyy-MM").offset(DateField.MONTH,-1).toString("yyyy-MM-dd");
            String curMonth = DateUtil.beginOfMonth(new Date()).toString("yyyyMM");

            familySalaryWriteService.updateEndDate(order.getSourOrderId(),lastMonth);
            Date now = new Date();
            OrderEntity sourceOrder = new OrderEntity();
            sourceOrder.setOrderId(order.getSourOrderId());
            sourceOrder.setEndMonth(lastMonth);
            sourceOrder.setEndDate(lastMonth);
            sourceOrder.setUpdateTime(now);
            sourceOrder.setUpdateBy(accountVo.getUserId());
            sourceOrder.setOperDate(now);
            sourceOrder.setOperator(accountVo.getUserId());
            orderWriteService.updateIgnoreNull(sourceOrder);
        }else if("0".equals(orderApproveDTO.getApprovalResult())){
            OrderEntity sourceOrder = new OrderEntity();
            sourceOrder.setUpdateTime(new Date());
            sourceOrder.setUpdateBy(accountVo.getUserId());
            sourceOrder.setOperDate(new Date());
            sourceOrder.setOperator(accountVo.getUserId());
            sourceOrder.setRecheckFlag(0);
            sourceOrder.setOrderId(order.getSourOrderId());
            orderWriteService.updateIgnoreNull(sourceOrder);

            restoreFamilyAndFamilyMember(orderApproveDTO.getOrderId());

            revokeBankAccount(order.getFamilyId(),order.getSourOrderId());
        }
    }


    @Override
    public void approveHouseholdCancel(OrderApproveDTO orderApproveDTO, UserAccountVo accountVo) {

        backlogService.approveHouseholdCancel(orderApproveDTO, accountVo);

        OrderEntity order = orderReadService.getOrderById(orderApproveDTO.getOrderId());
        if("1".equals(orderApproveDTO.getApprovalResult())) {

            this.changeLowerStatus(order.getOrderId(),order.getFamilyId(),order.getBusinessType());


            String lastMonth = DateUtil.parse(orderApproveDTO.getRescueYears(), "yyyy-MM").offset(DateField.MONTH,-1).toString("yyyy-MM-dd");
            String curMonth = DateUtil.beginOfMonth(new Date()).toString("yyyyMM");

            familySalaryWriteService.updateEndDate(order.getSourOrderId(),lastMonth);
            Date now = new Date();
            OrderEntity sourceOrder = new OrderEntity();
            sourceOrder.setOrderId(order.getSourOrderId());
            sourceOrder.setEndMonth(lastMonth);
            sourceOrder.setEndDate(lastMonth);
            sourceOrder.setUpdateTime(now);
            sourceOrder.setUpdateBy(accountVo.getUserId());
            sourceOrder.setOperDate(now);
            sourceOrder.setOperator(accountVo.getUserId());
            orderWriteService.updateIgnoreNull(sourceOrder);
        }else if("0".equals(orderApproveDTO.getApprovalResult())){
            OrderEntity sourceOrder = new OrderEntity();
            sourceOrder.setUpdateTime(new Date());
            sourceOrder.setUpdateBy(accountVo.getUserId());
            sourceOrder.setOperDate(new Date());
            sourceOrder.setOperator(accountVo.getUserId());
            sourceOrder.setRecheckFlag(0);
            sourceOrder.setOrderId(order.getSourOrderId());
            orderWriteService.updateIgnoreNull(sourceOrder);

            restoreFamilyAndFamilyMember(orderApproveDTO.getOrderId());
        }

        if(!Constant.AudtiOrApprovalResult.REJECT.equals(orderApproveDTO.getApprovalResult())){
            scheduleCheckService.sendApproveResult(Arrays.asList(orderApproveDTO.getOrderId()),Constant.BusinessCode.DIBAO,accountVo);
        }
    }


    public void changeLowerStatus(String orderId,String familyId,String businessType){
        if(Constant.BusinessCode.DIBAO.equals(businessType)){

            FamilyMainEntity familyMainEntity = familyMainReadService.getById(familyId);
        }

    }


    @Override
    public BaseResult<Boolean> addRecheckOrderNo(String [] orderIds, String batchNo, UserAccountVo accountVo) {
        String areaCode = accountVo.getAreaCode();
        List<CheckDTO> checkList = new ArrayList<CheckDTO>();
        String checkType =Constant.BusiCode.RECHECK_BATCH;
        if(orderIds != null){

            for (int i = 0; i < orderIds.length; i++) {
                if(StringUtils.isNotEmpty(orderIds[i])){
                    OrderEntity orderEnity = orderReadService.getOrderById(orderIds[i]);
                    CheckDTO dto =   getRecheckOrder(orderIds[i],batchNo);
                    dto.setFamilyId(orderEnity.getFamilyId());
                    checkList.add(dto);
                }
            }
        }

        BaseResult<Boolean>  rest = new BaseResult<>();
        checkWriteService.addCheckNo(checkList,batchNo,Constant.CheckState.SAVE,checkType );


        recheckWriteService.updateCountPersion(batchNo,Constant.BusiCode.RECHECK_BATCH,Constant.CheckState.SAVE);

        return rest;
    }





    @Override
    public BaseResult<Boolean> deleteRechekOrderNo(String[] orderIds, String[] checkIds, String batchNo, String state, String type) throws BizException{
        int count = 0 ;
        BaseResult<Boolean> result = new BaseResult<Boolean>(FailureCode.SUC_0.getCode(),FailureCode.SUC_0.getMessage());

        List <CheckEntity> listCheck = new ArrayList<>();
        List <String>  noCheckList = new ArrayList<>();

        for (int i = 0; i < checkIds.length; i++) {
            if(StringUtils.isNotEmpty(checkIds[i])){
                CheckParam param = getCheckParam( checkIds[i],batchNo,state,type,null);

                List<CheckEntity> checkEntityList =  checkReadService.moreConditionQuery(param);
                if(checkEntityList.size() > 0){
                    listCheck.add(checkEntityList.get(0));
                }else{
                    noCheckList.add(orderIds[i]);
                }
            }
        }

        if(listCheck.size() !=checkIds.length ){
            String name = "[";
            for (int i = 0; i < noCheckList.size(); i++) {
                OrderEntity orderEntity =  orderReadService.getOrderById(noCheckList.get(i));
                if(orderEntity!= null){
                    name +="," +  orderEntity.getName();
                }else{
                    throw new BizException(FailureCode.ERR_30003);
                }
            }
            String message = name + "]"+ FailureCode.ERR_30001.getMessage();
            throw new BizException(FailureCode.ERR_30001);
        }else{

            for (int i = 0; i < listCheck.size(); i++) {
               count +=checkWriteService.delete(listCheck.get(i));
            }
        }

        recheckWriteService.updateCountPersion(batchNo,Constant.BusiCode.RECHECK_BATCH,Constant.CheckState.SAVE);
         return result;
    }

    @Override
    public int  confirmInform(String[] batchNo, String status){
        return recheckWriteService.update(status,batchNo);
    }



    @Override
    public int   cancalInform(String status, String [] batchNo){
        return recheckWriteService.update(status,batchNo);


    }



    @Override
    public int   confirmCheck(String status, String[] batchNo){
        checkWriteService.update(batchNo,Constant.CheckState.WIAT_SEND);

        return recheckWriteService.updateStatusDate(status,batchNo);
    }

    private CheckParam getCheckParam( String checkId,String batchNo , String state , String type,String areaCode ){
        CheckParam param = new CheckParam();
        param.setCheckId(checkId);
        param.setCheckBatchNo(batchNo);
        param.setCheckState(state);
        param.setCheckType(type);
        param.setAreaCode(areaCode);
        return param;
    }






    private CheckDTO getRecheckOrder(String orderId, String batchNo){
        OrderEntity entity = orderReadService.getOrderById(orderId);
        if (entity == null) {
            throw new BizException(FailureCode.ERR_10003);
        }
        String newOrderId = IdUtil.simpleUUID();

        FamilyMainEntity family = familyMainReadService.getById(entity.getFamilyId());

        CheckDTO dto  = getCheckDTO(batchNo,newOrderId,orderId,family);
        return dto;
    }



    private  CheckDTO getCheckDTO(String batchNo ,String newOrderId,String orderId, FamilyMainEntity family ){
        CheckDTO dto = new CheckDTO();
        dto.setCheckBatchNo(batchNo);
        dto.setCheckId(newOrderId);
        dto.setFamilyId(family.getId());
        dto.setIdcard(family.getIdcard());
        dto.setAreaCode(family.getAreaCode());
        dto.setOrderId(orderId);
        return dto;
    }


    private String checkIfMeetConditionsOfRecheck(OrderEntity order) {

        if (order == null) {
            throw new BizException(FailureCode.ERR_10003);
        }


        if(!Constant.BizState.APPROVE_YES.equals(order.getState())) {
            throw new BizException(FailureCode.ERR_20011);
        }


        String startMonthStr = familySalaryReadService.getStatDateByOrderId(order.getOrderId());
        if(!CommonUtil.invalidArgs(startMonthStr) && DateUtil.beginOfMonth(DateUtil.parse(startMonthStr))
                .after(DateUtil.beginOfMonth(new Date()))) {
            throw new BizException("-1","当前家庭有跨月待生效业务，无法复查登记");
        }

        String recheckOrderId = null;

        if (Constant.RECHECK_FLAG.YES == order.getRecheckFlag()) {
            recheckOrderId = orderReadService.getIdBySourceId(order.getOrderId());
        }

        return recheckOrderId;
    }


    public void backupFamilyAndFamilyMember(String familyId, String newOrderId) {

        FamilyMainEntity family = familyMainReadService.getById(familyId);
        List<FamilyMemberEntity> familyMemberList = familyMemberReadService.listByFamilyId(familyId);


        FamilyMainTempEntity familyTemp = new FamilyMainTempEntity();
        BeanUtils.copyProperties(family,familyTemp);
        familyTemp.setOrderId(newOrderId);
        familyTemp.setFamilyId(family.getId());
        List<FamilyMemberTempEntity> familyMemberTempList = new ArrayList<>();
        for (FamilyMemberEntity member: familyMemberList) {
            FamilyMemberTempEntity memberTemp = new FamilyMemberTempEntity();
            BeanUtils.copyProperties(member,memberTemp);
            memberTemp.setOrderId(newOrderId);
            memberTemp.setMemberId(member.getId());
            memberTemp.setFamilyId(family.getId());
            familyMemberTempList.add(memberTemp);
        }
        familyMainTempWriteService.saveFamilyTemp(familyTemp);
        familyMemberTempWriteService.saveBatchFamilyMemberTemp(familyMemberTempList);
    }


    public void restoreFamilyAndFamilyMember(@V({"notnull"}) String recheckOrderId) {

        FamilyMainTempEntity familyTemp = familyMainTempReadService.getById(recheckOrderId);
        List<FamilyMemberTempEntity> familyMemberTempList = familyMemberTempReadService.getByOrderId(recheckOrderId);


        FamilyMainEntity family = new FamilyMainEntity();
        BeanUtils.copyProperties(familyTemp,family);
        family.setId(familyTemp.getFamilyId());
        List<FamilyMemberEntity> familyMemberList = new ArrayList<>();
        for (FamilyMemberTempEntity memberTemp: familyMemberTempList) {
            FamilyMemberEntity member = new FamilyMemberEntity();
            BeanUtils.copyProperties(memberTemp,member);
            member.setId(memberTemp.getMemberId());
            familyMemberList.add(member);
        }
        familyMainWriteService.updateFamily(family);
        familyMemberWriteService.batchUpdateIgnoreNull(familyMemberList);
    }


    @Override
    public void cancelSalvationRequestTown(String orderId,String revokeReason, UserAccountVo userAccountVo){

        OrderStateVerifyDTO orderStateVerifyDTO = orderReadService.getBizStateReportFile(orderId);


        ruleEngineReadService.getBizStateRuleThrow(Constant.OrderBizStateType.TOWN_REVOKE, orderStateVerifyDTO, userAccountVo);


        orderWriteService.backUpOrder(orderStateVerifyDTO);


        OrderDetailEntity orderDetailEntity = new OrderDetailEntity();
        orderDetailEntity.setOrderId(orderId);
        orderDetailEntity.setCheckType(Constant.CheckDatailStatus.revoke);
        orderDetailEntity.setBusinessStatus(Constant.RemarkOperType.STREET);
        orderDetailEntity.setCheckResult(Constant.AudtiOrApprovalResult.REVOKE);
        orderDetailEntity.setCheckOpinion(revokeReason);
        orderDetailEntity.setCheckPeople(userAccountVo.getUsername());
        orderDetailEntity.setCheckDate(new Date());
        orderDetailEntity.setOperator(userAccountVo.getLoginId());
        orderDetailEntity.setCreateBy(userAccountVo.getUserId());
        orderDetailEntity.setOrgId(userAccountVo.getOrgId());
        orderDetailWriteService.insertSalvationAudit(orderDetailEntity);


        familySalaryWriteService.deleteSalaryByOrderId(orderId);


        noticeBoardDetailWriteService.deleteByOrderId(orderId);
    }



    @Override
    public Map<String, List<String>> cancelSalvationRequestTowns(List<String> orderIdList, UserAccountVo userAccountVo){
        Map<String, List<String>> idcardCheckRstMsg = new HashMap<>();

        List<OrderStateVerifyDTO> orderStateVerifyList = orderReadService.getBizStateReportFileList(orderIdList);
        List<String> notStateIdcardList = new ArrayList<>();


        orderStateVerifyList.forEach(orderStateVerifyDTO -> {

            orderStateVerifyDTO.setNextCondition("4");
            boolean mark = ruleEngineReadService.getBizStateRule(Constant.OrderBizStateType.TOWN_DELETE, orderStateVerifyDTO, userAccountVo);
            if(mark){

                orderWriteService.revokeOrder(orderStateVerifyDTO);

                this.revokeFamily(orderStateVerifyDTO.getFamilyId(), orderStateVerifyDTO.getSourOrderId());

                this.revokeBankAccount(orderStateVerifyDTO.getFamilyId(),orderStateVerifyDTO.getSourOrderId());

                scheduleCheckService.repealUnfinishCheck(orderStateVerifyDTO.getOrderId(),userAccountVo);

                suspendManagementService.updateSuspendFamily(orderStateVerifyDTO.getOrderId(),Constant.BizStateNew.TOWN_DELETE);
            }else{
                notStateIdcardList.add(orderStateVerifyDTO.getIdcard());
            }
        });
        if (CollectionUtils.isNotEmpty(notStateIdcardList)) {
            idcardCheckRstMsg.put("noExistState", notStateIdcardList);
        }

        return idcardCheckRstMsg;
    }


    public void revokeFamily(String familyId, String orderId){

        familyMainWriteService.updateMainByMainHistory(familyId, orderId);


        familyMemberWriteService.updateMemberByMainHistory(familyId, orderId);
    }

    public void revokeBankAccount(String familyId,String orderId){
        OrderEntity entity = orderReadService.getById(orderId);
        bankWriteService.resetBankAccountByFamilyId(familyId,entity.getMemberId());
    }


    public void backupMemberAssets(String familyId,String newOrderId,String orderId){
        List<MemberAssetsEntity> memberList = memberAssetsReadService.queryListByFamilyIds(familyId,orderId);
        List<MemberAssetsEntity> memberTempList = new ArrayList<>();

        for (MemberAssetsEntity member: memberList) {
            MemberAssetsEntity memberTemp = new MemberAssetsEntity();
            BeanUtils.copyProperties(member,memberTemp);
            memberTemp.setOrderId(newOrderId);
            memberTemp.setId(Constant.getUUID());
            memberTempList.add(memberTemp);
        }
        if(CollectionUtils.isNotEmpty(memberTempList)){
            memberAssetsWriteService.saveBatchMemberAssetsTemp(memberTempList);
        }

    }

    @Override
    public ApplyRtnDTO tempSaveRecheckInHouse(MininumLivingApplyDTO applyDto, UserAccountVo accountVo) {

        this.isCanTempSaveInHouse(applyDto, accountVo);

        this.verifyFamilyMasterNum(applyDto.getFamilyId());

        int count = familyMemberReadService.isHouseholdCancel(applyDto.getOrderId());
        if(count>0){

            this.verifyCompleteMemberInfo(applyDto.getFamilyId(),applyDto.getStandType());
        }else{

            this.verifyMemberAssets(applyDto.getOrderId());

            this.verifyCompleteMemberInfo(applyDto.getFamilyId(),applyDto.getStandType());

            this.verifyCert(applyDto.getOrderId(), applyDto.getFamilyId());
        }


        ApplyRtnDTO applyRtnDTO = this.saveSalvationRequest(applyDto, accountVo);


        String inHouseId = this.saveOrderInHouse(applyDto, accountVo);
        applyRtnDTO.setOrderInhouseId(inHouseId);


        return applyRtnDTO;
    }


    public void isCanTempSaveInHouse(MininumLivingApplyDTO applyDto, UserAccountVo accountVo){


        OrderStateVerifyDTO orderStateVerifyDTO = orderReadService.getBizStateReportFile(applyDto.getOrderId());

        orderStateVerifyDTO.setNextCondition(orderStateVerifyDTO.getBizState());


        ruleEngineReadService.getRecheckBizStateRuleThrow(Constant.OrderBizStateType.START_TOWN_IN_HOUSE, orderStateVerifyDTO, accountVo);


        applyDto.setOrderBizState(orderStateVerifyDTO.getNextBizState());
    }


    @Override
    public ApplyRtnDTO completeRecheckInHouse(MininumLivingApplyDTO applyDto, UserAccountVo accountVo) {

        this.isCanCompleteInHouse(applyDto, accountVo);


        this.verifyFamilyMasterNum(applyDto.getFamilyId());


        int count = familyMemberReadService.isHouseholdCancel(applyDto.getOrderId());
        if(count>0){

            this.verifyCompleteMemberInfo(applyDto.getFamilyId(),applyDto.getStandType());


            this.verifyOrderInHouse(applyDto);
        }else{

            this.verifyMemberAssets(applyDto.getOrderId());


            this.verifyCompleteMemberInfo(applyDto.getFamilyId(),applyDto.getStandType());


            this.verifyOrderInHouse(applyDto);


            this.verifyCert(applyDto.getOrderId(), applyDto.getFamilyId());
        }


        ApplyRtnDTO applyRtnDTO = this.saveSalvationRequest(applyDto, accountVo);


        String inHouseId = this.saveOrderInHouse(applyDto, accountVo);
        applyRtnDTO.setOrderInhouseId(inHouseId);


        return applyRtnDTO;
    }


    public void isCanCompleteInHouse(MininumLivingApplyDTO applyDto, UserAccountVo userAccountVo){


        OrderStateVerifyDTO orderStateVerifyDTO = orderReadService.getBizStateReportFile(applyDto.getOrderId());

        orderStateVerifyDTO.setNextCondition(orderStateVerifyDTO.getBizState());
        if(Constant.UserLevel.STREET.equals(userAccountVo.getAreaLevel())){

            orderStateVerifyDTO.setNextCondition(orderStateVerifyDTO.getBizState());
        }

        ruleEngineReadService.getRecheckBizStateRuleThrow(Constant.OrderBizStateType.COMPLETE_TOWN_IN_HOUSE, orderStateVerifyDTO, userAccountVo);


        applyDto.setOrderBizState(orderStateVerifyDTO.getNextBizState());
        applyDto.setOrderState(orderStateVerifyDTO.getNextState());
    }


    public void verifyFamilyMasterNum(String familyId){
        int rst = familyMemberReadService.cntFamilyMaster(familyId);
        if(rst > 1){
            throw new BizException(FailureCode.ERR_10080);
        }
        if(rst == 0){
            throw new BizException(FailureCode.ERR_10081);
        }
    }

    public void verifyMemberAssets(String orderId){

        int count =  orderReadService.selectOrderInCalculate(orderId);
        if(count<1){

            int rst = memberAssetsReadService.cntOrderAssets(orderId);
            if(rst <= 0){
                throw new BizException(FailureCode.ERR_20068);
            }
        }else{

            int rst = incomeCalculateReadService.selectCountByOrderId(orderId);
            if(rst<=0){
                throw new BizException(FailureCode.ERR_20087);
            }
        }
    }


    public void verifyCompleteMemberInfo(String familyId,String standType){
        String rst = familyMemberReadService.cntCompleteInfoNum(familyId, Constant.BusinessCode.DIBAO,standType);

        if(!CommonUtil.invalidArgs(rst)){
            throw new BizException(FailureCode.ERR_20067);
        }
    }

    public void verifyCert(String orderId, String familyId){
        int rst = familyMemberReadService.cntFamilyMember(familyId);
        if(rst<1) {

            Map<String, Long> cntMap = orderCertReadService.cntFamilyCertNum(orderId, familyId);
            if (cntMap.containsKey("familyRegisterNum") && cntMap.get("familyRegisterNum") <= 0) {
                throw new BizException("-1", "当前家庭没有上传【户口本】资料，请上传！");
            }

            if (cntMap.containsKey("checkAuthorizationNum") && cntMap.get("checkAuthorizationNum") <= 0) {
                throw new BizException("-1", "当前家庭没有上传【救助申请家庭经济状况核对授权书】，请上传！");
            }

            List<String> memberIdcardNumMap = orderCertReadService.cntMemberIdcardNum(orderId, familyId);
            if (CollectionUtils.isNotEmpty(memberIdcardNumMap)) {
                throw new BizException("-1", "当前成员【" + String.join(",", memberIdcardNumMap) + "】没有上传身份证，请先上传身份证");
            }
        }

        List<String> supportNoIdCardName = orderCertReadService.cntSupportIdCardNum(orderId, familyId);
        if(CollectionUtils.isNotEmpty(supportNoIdCardName)){
            throw new BizException("-1", "当前赡抚养人【" + String.join(",", supportNoIdCardName) + "】没有上传身份证，请先上传身份证");
        }

        int count = orderCertReadService.selectSupportAuthor(familyId,orderId);
        if(count>0){
            throw new BizException(FailureCode.ERR_20085);
        }
    }

    public ApplyRtnDTO saveSalvationRequest(MininumLivingApplyDTO applyDto, UserAccountVo accountVo){

        if(CommonUtil.invalidArgs(applyDto.getOrderId())){

            if(Constant.DomesticRelation.ONESELF.equals(applyDto.getFamilyRelation())){
                applyDto.setName(applyDto.getApplyName());
                applyDto.setIdcard(applyDto.getApplyIdcard());
            }
        }else{

            FamilyMemberEntity masertInfo = familyMemberReadService.getMasertInfo(applyDto.getFamilyId());
            if(!CommonUtil.invalidArgs(masertInfo)){
                applyDto.setMemberId(masertInfo.getId());
                applyDto.setName(masertInfo.getName());
                applyDto.setIdcard(masertInfo.getIdcard());
            }
        }

        FamilyMainEntity familyMainEntity = ApplyConvert.convertToFamilyMainEntity(applyDto, accountVo);
        FamilyMemberEntity memberEntity = ApplyConvert.convertToFamilyMemberEntity(applyDto, accountVo);


        if (Constant.OrderType.NEW.equals(applyDto.getType())) {
            memberSalaryReadService.checkMemberIsSaved(applyDto.getOrderId(), memberEntity.getId(), com.mcxx.util.DateUtil.getMonthString());
        }


        ApplyRtnDTO applyRtnDTO = familyMainWriteService.addFamilyAndMember4Apply(familyMainEntity, memberEntity, applyDto.getMemberOldState(), accountVo,applyDto.getType());


        OrderEntity orderEntity = this.saveOrder(applyDto, applyRtnDTO, accountVo);


        applyRtnDTO.setOrderId(orderEntity.getOrderId());
        applyRtnDTO.setStandType(applyDto.getStandType());
        applyRtnDTO.setOrderBizState(orderEntity.getBizState());
        return applyRtnDTO;
    }


    public OrderEntity saveOrder(MininumLivingApplyDTO applyDto, ApplyRtnDTO applyRtnDTO, UserAccountVo accountVo){

        applyDto.setFamilyId(applyRtnDTO.getFamilyId());

        if(CommonUtil.invalidArgs(applyDto.getMemberId()) &&  Constant.DomesticRelation.ONESELF.equals(applyDto.getFamilyRelation()) ){
            applyDto.setMemberId(applyRtnDTO.getMemberId());
        }
        OrderEntity orderEntity = ApplyConvert.convertToOrderEntity(applyDto, accountVo);
        orderEntity.setBusinessType(Constant.BusinessCode.DIBAO);


        if (org.apache.commons.lang3.StringUtils.isEmpty(applyDto.getOrderId())) {

            orderEntity.setOrderId(IdUtil.simpleUUID());
            orderEntity.setState(Constant.BizState.SALVATION);
            orderEntity.setBizState(Constant.BizState.SALVATION);
            orderWriteService.insertIgnoreNull(orderEntity);
        } else {
            if(!CommonUtil.invalidArgs(applyDto.getOrderBizState())){
                orderEntity.setBizState(applyDto.getOrderBizState());
            }
            if(!CommonUtil.invalidArgs(applyDto.getOrderState())){
                orderEntity.setState(applyDto.getOrderState());
            }

            orderWriteService.updateIgnoreNull(orderEntity);
        }
        return orderEntity;
    }

    public String saveOrderInHouse(MininumLivingApplyDTO applyDto, UserAccountVo userAccountVo) {

        if(CommonUtil.invalidArgs(applyDto.getCheckPeople()) || CommonUtil.invalidArgs(applyDto.getCheckDate())
                || CommonUtil.invalidArgs(applyDto.getCheckContent())){

            return null;
        }


        OrderInHouseDTO inHouseDTO = ApplyConvert.convertToInhouseEntity(applyDto);


        if(CommonUtil.invalidArgs(inHouseDTO.getId())){
            inHouseWriteService.addInHouse(inHouseDTO, applyDto.getInhouseCertIdList(), userAccountVo);
        }else{
            inHouseWriteService.updateById(inHouseDTO, applyDto.getInhouseCertIdList(), userAccountVo);
        }
        return inHouseDTO.getId();
    }

    public void verifyOrderInHouse(MininumLivingApplyDTO applyDto){

        if(CommonUtil.invalidArgs(CommonUtil.invalidArgs(applyDto.getCheckPeople()) || CommonUtil.invalidArgs(applyDto.getCheckDate())
                || CommonUtil.invalidArgs(applyDto.getCheckContent()))){
            throw new BizException(FailureCode.ERR_20014);
        }


        if(CollectionUtils.isNotEmpty(applyDto.getInhouseCertIdList())){

            return;
        }

        int rst = orderCertReadService.cntInhouseCertNum(applyDto.getOrderId(), applyDto.getOrderInhouseId());
        if(rst <= 0){
            throw new BizException("-1", "当前家庭没有上传【入户调查辅证材料】，请上传！");
        }
    }


    @Override
    public ExcelInfo exportExcelRecheckResultList(RecheckParam param, UserAccountVo accountVo){
        ExcelInfo excelInfo = null;
        QueryParamUtil.setBaseParamValue(param,accountVo);
        List<OrderSimpleExcelDTO> list  = orderReadService.exportRecheckResultList(param,accountVo);

        excelInfo = exportExcelService.exportOrgOpLogs(OrderSimpleExcelDTO.class,list,"低保复查结果对象信息.xls",
                "低保复查结果对象列表","低保复查结果对象列表",false,null);


        return excelInfo;
    }


    @Override
    public ExcelInfo exportExcelRecheckToDoList(RecheckOrderQueryParam param, UserAccountVo accountVo){
        ExcelInfo excelInfo = null;
        QueryParamUtil.setBaseParamValue(param,accountVo);
        List<RechckToDoOrderListExcelDTO> list  = orderReadService.exportRecheckToDoList(param,accountVo);

        excelInfo = exportExcelService.exportOrgOpLogs(RechckToDoOrderListExcelDTO.class,list,"低保复查待办对象信息.xls",
                "低保复查待办对象列表","低保复查待办对象列表",false,null);


        return excelInfo;
    }

    @Override
    public ExcelInfo exportCountRecheckTodoList(RecheckOrderQueryParam param, UserAccountVo accountVo){
        ExcelInfo excelInfo = null;
        QueryParamUtil.setBaseParamValue(param,accountVo);
        List<RechckToDoOrderListExcelDTO> list  = orderReadService.exportCountRecheckTodoList(param,accountVo);


        String businessType = "";
        if(param.getBusinessType().equals(Constant.BusinessCode.DIBAO)) {
            businessType = "低保";
        }else if(param.getBusinessType().equals(Constant.BusinessCode.TEKUN)) {
            businessType = "特困";
        }

        excelInfo = exportExcelService.exportOrgOpLogs(RechckToDoOrderListExcelDTO.class,list,businessType+"复查区县待办对象信息.xls",
                businessType+"区县复查待办对象列表",businessType+"区县复查待办对象列表",false,null);


        return excelInfo;
    }

    @Override
    public int repealCheck(String checkId,UserAccountVo accountVo){
        CheckEntity entity = checkReadService.selectUnFinishCheck(checkId);
        if(CommonUtil.invalidArgs(entity)){
            return 0;
        }
        if(Constant.CheckState.FORWARD_RESULT.equals(entity.getCheckState()) && StringUtils.isNotEmpty(entity.getCheckReportFile())){
            throw new BizException("-1","已完成的核对不能撤销");
        }

        String countyCode = accountVo.getAreaCode().substring(0,6);
        if(Arrays.stream(CheckWriteService.IntegrateAreaCode).filter(o->o.equals(countyCode)).findAny().isPresent()){
           return integrateCheckService.repealCheck(entity,accountVo);
        }
        return 1;
    }

    @Override
    public int decideIncome(String orderId,String familyId){
        return  checkReadService.decideIncome(orderId,familyId);

    }


    @Override
    public void backSalvationFinished(String orderId, String revokeReason, UserAccountVo userAccountVo){

        OrderEntity orderEntity = orderReadService.getOrderById(orderId);


        this.checkCountryRevoke(orderEntity);


        OrderEntity orderEntityForUpdate = new OrderEntity();
        orderEntityForUpdate.setBizState(Constant.BizStateNew.APPROVE_ING);
        orderEntityForUpdate.setOrderId(orderId);
        orderEntityForUpdate.setFamilyId(orderEntity.getFamilyId());
        orderEntityForUpdate.setState(Constant.BizStateNew.APPROVE_ING);
        orderEntityForUpdate.setCheckDate(null);
        orderEntityForUpdate.setCheckDept("");
        orderEntityForUpdate.setStartMonth("");
        orderEntityForUpdate.setEndMonth("");
        orderWriteService.updateForCountryRevoke(orderEntityForUpdate);


        OrderDetailEntity orderDetailEntity = new OrderDetailEntity();
        orderDetailEntity.setOrderId(orderId);
        orderDetailEntity.setCheckType(Constant.CheckDatailStatus.revoke);
        orderDetailEntity.setBusinessStatus(Constant.RemarkOperType.COUNTY);
        orderDetailEntity.setCheckResult(Constant.AudtiOrApprovalResult.REVOKE);
        orderDetailEntity.setCheckOpinion(revokeReason);
        orderDetailEntity.setCheckPeople(userAccountVo.getUsername());
        orderDetailEntity.setCheckDate(new Date());
        orderDetailEntity.setOperator(userAccountVo.getLoginId());
        orderDetailEntity.setOrgId(userAccountVo.getOrgId());
        orderDetailEntity.setCreateBy(userAccountVo.getUserId());
        orderDetailWriteService.insertSalvationAudit(orderDetailEntity);


        familyMemberHistoryWriteService.deleteByOrderId(orderId);

        salaryChangeWriteService.deleteBackByOrderId(orderId);
        OrderEntity oldOrderEntity = orderReadService.getOrderById(orderEntity.getSourOrderId());
        oldOrderEntity.setEndMonth("2100-01-01");
        orderWriteService.updateIgnoreNull(oldOrderEntity);

        if(Constant.BizStateNew.APPROVE_YES.equals(orderEntity.getState())){

            familySalaryWriteService.updateEndDate(orderEntity.getSourOrderId(),"2100-01-01");
            suspendManagementService.backupSuspendFamily(orderEntity.getOrderId(),Constant.SuspendState.S_STOP,orderEntity.getSourOrderId());
        }else{
            suspendManagementService.backupSuspendFamily(orderEntity.getOrderId(),Constant.SuspendState.S_SUSPEND,orderEntity.getSourOrderId());
        }

    }


    public void checkCountryRevoke(OrderEntity orderEntity){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");


        System.out.println(orderEntity.getState());
        if(!(Constant.BizStateNew.APPROVE_REFUSE.equals(orderEntity.getState()) || Constant.BizStateNew.APPROVE_YES.equals(orderEntity.getState()))){
            throw new BizException("-1", "只可以撤销审批完成的数据！");
        }


        if (Integer.parseInt(com.mcxx.util.DateUtil.getMonthString().replaceAll("-", "")) - Integer.parseInt(sdf.format(orderEntity.getCheckDate())) >= 1 ) {
            throw new BizException("-1", "不能撤销当前月之前的审核记录");
        }


        String checkOtherOrder = orderReadService.getIdBySourceId(orderEntity.getSourOrderId());
        if(checkOtherOrder!=null &&  !checkOtherOrder.equals(orderEntity.getOrderId())) {
            throw new BizException("-1", "该数据已生成其他业务，不可撤销");
        }


        String orderId = orderReadService.getDataBySourceId(orderEntity.getOrderId());
        if(!StringUtils.isEmpty(orderId)){
            throw new BizException("-1", "该数据已生成其他业务，不可撤销");
        }


        if(orderEntity.getStartMonth()!=null && Constant.BizStateNew.APPROVE_YES.equals(orderEntity.getState())){
            fundPayReadService.verifyFundPayByOrderId(orderEntity.getBusinessType(), orderEntity.getCountyCode(),
                    orderEntity.getStandType(), orderEntity.getStartMonth(), orderEntity.getSupplyType(),
                    Constant.FundType.CAPITAL_FUND_PAY,orderEntity.getOrderId());
        }


        List<FamilyMemberEntity> list = familyMemberReadService.listHistroyByOrderId(orderEntity.getOrderId());
        if(list.size()==0) {
            list = familyMemberReadService.listByFamilyId(orderEntity.getFamilyId());
        }
        for (FamilyMemberEntity member:list) {

            familyMemberReadService.checkIdcardForRevoke(member.getIdcard());
        }

    }

}
